using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Terra.Core.Common.ApiResponse;   // 引入ApiResponse和ApiResponseCode
using Terra.Core.Common.ErrorCodes.Constants;
using Terra.Core.Common.ErrorCodes.Models;

namespace Terra.Core.Common.Filters
{
    /// <summary>
    /// 统一处理ASP.NET Core模型验证错误的过滤器
    /// </summary>
    /// <remarks>
    /// 该过滤器用于统一处理来自数据注解([Required]、[EmailAddress]等)的验证错误，
    /// 转换为符合API响应格式的标准化错误结构。
    /// </remarks>
    public class ValidationFilter : IAsyncActionFilter
    {
        /// <summary>
        /// 在控制器动作执行前后运行的异步方法
        /// </summary>
        /// <param name="context">动作执行上下文</param>
        /// <param name="next">下一个过滤器的委托</param>
        /// <returns>异步任务</returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 如果模型状态无效，拦截请求并返回统一的错误响应
            if (!context.ModelState.IsValid)
            {
                // 提取错误详情，按字段分组
                var validationErrors = GetValidationErrors(context.ModelState);

                // 构建标准化响应
                var response = BuildApiResponse(validationErrors);

                // 设置跟踪ID
                response.TraceId = context.HttpContext.TraceIdentifier;

                // 使用422状态码(Unprocessable Entity)，表示服务器理解请求但无法处理
                context.Result = new UnprocessableEntityObjectResult(response);
                return; // 重要：阻止进一步执行
            }

            // 如果验证通过，执行下一个过滤器或动作
            await next();
        }

        /// <summary>
        /// 从ModelState中提取验证错误详情
        /// </summary>
        /// <param name="modelState">模型状态字典</param>
        /// <returns>验证错误字典，键为字段名，值为错误消息数组</returns>
        private Dictionary<string, string[]> GetValidationErrors(ModelStateDictionary modelState)
        {
            var errors = new Dictionary<string, string[]>();

            foreach (var key in modelState.Keys)
            {
                // 获取指定字段的错误集合
                var errorEntries = modelState[key]?.Errors;
                if (errorEntries != null && errorEntries.Count > 0)
                {
                    // 对每个错误消息进行转换和本地化
                    var errorMessages = errorEntries
                        .Select(error => TranslateValidationMessage(error.ErrorMessage, key))
                        .ToArray();

                    // 将字段名和对应的错误消息数组添加到字典
                    errors.Add(key, errorMessages);
                }
            }

            return errors;
        }

        /// <summary>
        /// 构建标准化的API响应
        /// </summary>
        /// <param name="validationErrors">验证错误字典</param>
        /// <returns>API响应对象</returns>
        private ApiResponse.ApiResponse BuildApiResponse(Dictionary<string, string[]> validationErrors)
        {
            // 从错误集合中提取所有错误消息
            var allErrorMessages = validationErrors.Values
                .SelectMany(messages => messages)
                .ToList();

            // 默认错误消息
            string errorMessage = "提交的数据验证失败";

            // 如果有具体错误，使用第一个错误作为主要错误消息
            if (allErrorMessages.Count > 0)
            {
                errorMessage = allErrorMessages[0];
            }

            // 创建响应对象
            var response = ApiResponse.ApiResponse.Error(
                code: SystemErrorCodes.ValidationFailed, // 使用系统预定义的验证失败错误码
                message: errorMessage, // 使用验证错误消息
                severity: ErrorSeverity.Warning // 设置为警告级别
            );

            // 将所有验证错误添加到响应的Data属性中
            response.Data = validationErrors;

            return response;
        }

        /// <summary>
        /// 将验证错误消息转换为中文
        /// </summary>
        /// <param name="errorMessage">原始错误消息</param>
        /// <param name="fieldName">字段名</param>
        /// <returns>转换后的错误消息</returns>
        private string TranslateValidationMessage(string errorMessage, string fieldName)
        {
            // 获取字段的友好显示名称
            string displayName = GetFieldDisplayName(fieldName);

            // 翻译常见验证错误消息
            if (errorMessage.Contains("field is required"))
                return $"{displayName}是必填项";

            if (errorMessage.Contains("valid e-mail address"))
                return $"{displayName}格式不正确，请输入有效的电子邮件地址";

            if (errorMessage.Contains("'Password' and 'ConfirmPassword' do not match"))
                return "两次输入的密码不一致";

            if (errorMessage.Contains("maximum length"))
                return $"{displayName}超出最大长度限制";

            if (errorMessage.Contains("minimum length"))
                return $"{displayName}长度不足最小要求";

            if (errorMessage.Contains("valid phone number"))
                return $"{displayName}格式不正确，请输入有效的电话号码";

            // 更多验证错误消息翻译...

            // 通用错误消息处理：如果没有特定的翻译，保留原始消息但添加字段名
            if (!errorMessage.Contains(displayName))
                return $"{displayName}: {errorMessage}";

            return errorMessage;
        }

        /// <summary>
        /// 获取字段的友好显示名称
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <returns>字段的友好显示名称</returns>
        private string GetFieldDisplayName(string fieldName)
        {
            // 去除可能的前缀和索引
            string name = fieldName;
            if (name.Contains("."))
            {
                name = name.Split('.').Last();
            }
            if (name.Contains("["))
            {
                name = name.Split('[')[0];
            }

            // 常见字段名映射
            return name switch
            {
                "UserName" => "用户名",
                "Password" => "密码",
                "ConfirmPassword" => "确认密码",
                "Email" => "电子邮箱",
                "PhoneNumber" => "手机号码",
                "RealName" => "真实姓名",
                "NickName" => "昵称",
                "BirthDate" => "出生日期",
                "Gender" => "性别",
                "Address" => "地址",
                "Title" => "标题",
                "Content" => "内容",
                "Description" => "描述",
                "Name" => "名称",
                "Code" => "编码",
                "StartTime" => "开始时间",
                "EndTime" => "结束时间",
                "CreatedTime" => "创建时间",
                "UpdatedTime" => "更新时间",
                "Status" => "状态",
                "Type" => "类型",
                "Remark" => "备注",
                _ => name // 默认返回原字段名
            };
        }
    }
}
